/**
 * Node
 * 
 * A node element of a Linked-List binary tree
 */

public class Node {
    protected int element;
    protected Node parent = null, left = null, right = null;
    
    // Constructors
    public Node() { }
    public Node(int e) {
        element = e;
    }
    
    // Getters
    public int getElement() {
        return element;
    }
    public Node getParent() {
        return parent;
    }
    public Node getLeftSibling() {
        return this.hasParent() ? this.getParent().getLeftChild() : null;
    }
    public Node getRightSibling() {
        return this.hasParent() ? this.getParent().getRightChild() : null;
    }
    public Node getLeftChild() {
        return left;
    }
    public Node getRightChild() {
        return right;
    }
    /*public Node getLeftSibling() {
        int depth = 0;
        Node temp = this;
        boolean atTarget = false;
        while(!atTarget) {
            if (temp.hasParent()) {
                temp = temp.getParent();
                ++depth;
            } else {
                // Special case for the root of the tree and its left subtree
                temp = null;
                return temp;
            }
            if(temp.isRightChild()) {
                temp = temp.getParent();
                ++depth;
                atTarget = true;
            }
        }
        while(depth > 0) {
            if(temp.hasLeftChild()) {
                temp = temp.getLeftChild();
                --depth;
            } else {
                // Not enough left children to get to a left sibling of this node
                temp = null;
                return temp;
            }
        }
        return temp;
    }*/
    /*public Node getRightSibling() {
        int depth = 0;
        Node temp = this;
        boolean atTarget = false;
        while(!atTarget) {
            if (temp.hasParent()) {
                temp = temp.getParent();
                ++depth;
            } else {
                // Special case for the root of the tree and its right subtree
                temp = null;
                return temp;
            }
            if(temp.isRightChild() || temp.isRoot()) { atTarget = true; }
        }
        while(depth > 0) {
            if(temp.hasRightChild()) {
                temp = temp.getRightChild();
                --depth;
            } else {
                // Not enough left children to get to a left sibling of this node
                temp = null;
                return temp;
            }
        }
        if(temp == this) { temp = null; }
        return temp;
    }*/
    
    // Setters
    public void setElement(int e) {
        element = e;
    }
    public void setParent(Node n) {
        parent = n;
    }
    public void setLeftChild(Node n) {
        left = n;
    }
    public void setRightChild(Node n) {
        right = n;
    }
    
    // Booleans
    public boolean hasParent() {
        return this.getParent() != null;
    }
    public boolean hasSibling() {
        if(this.isLeftChild()) { return this.getParent().hasRightChild(); }
        else { return this.getParent().hasLeftChild(); }
    }
    public boolean hasLeftSibling() {
        if(this.isRightChild() && this.hasSibling()) { return true; }
        else { return false; }
    }
    public boolean hasRightSibling() {
        if(this.isLeftChild() && this.hasSibling()) { return true; }
        else { return false; }
    }
    public boolean hasLeftChild() {
        return this.getLeftChild() != null;
    }
    public boolean hasRightChild() {
        return this.getRightChild() != null;
    }
    public boolean isRoot() {
        return !this.hasParent();
    }
    public boolean isLeftChild() {
        return this.getParent() == null ? false : this.getParent().getLeftChild() == null ? false : this.getParent().getLeftChild() == this;
    }
    public boolean isRightChild() {
        return this.getParent() == null ? false : this.getParent().getRightChild() == null ? false : this.getParent().getRightChild() == this;
    }
}